<?php

namespace RedMVC;

/**
 * Random class
 *
 * @category    RedMVC
 * @author      Jan Fischer, bitWorking <info@bitworking.de>
 */
class Random{

    const DIGITS                    = 1;
    const ALPHA_LOWER               = 2;
    const ALPHA_UPPER               = 4;
    const SPECIALCHARS              = 8;
    const ALL                       = 15;
    
    protected static $_digits       = '0123456789';
    protected static $_alphaLower   = 'abcdefghijklmnopqrstuvwxyz';
    protected static $_alphaUpper   = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    protected static $_specialchars = '#&@$_%?+';

    /**
     * replaces the special chars
     *
     * @param string $chars
     */
    public static function setSpecialChars($chars){
        self::$_specialchars = $chars;
    }

    /**
     * generates a random string
     *
     * @param int $length
     * @param int $useBits
     * @return string
     */
    public static function generate($length = 8, $useBits = self::ALL){
                
        $chars = array();

        if(($useBits & self::DIGITS) === self::DIGITS){
            $chars = array_merge($chars, str_split(self::$_digits));
        }
        if(($useBits & self::ALPHA_LOWER) === self::ALPHA_LOWER){
            $chars = array_merge($chars, str_split(self::$_alphaLower));
        }
        if(($useBits & self::ALPHA_UPPER) === self::ALPHA_UPPER){
            $chars = array_merge($chars, str_split(self::$_alphaUpper));
        }
        if(($useBits & self::SPECIALCHARS) === self::SPECIALCHARS){
            $chars = array_merge($chars, str_split(self::$_specialchars));
        }

        $out = '';
        for($i=0;$i<$length;$i++){
            $rand = mt_rand(0, count($chars)-1);
            $out .= $chars[$rand];
        }
        return $out;
    }

    /**
     * generates a digit between $min and $max
     *
     * @param int|null $min
     * @param int|null $max
     * @return int
     */
    public static function digit($min = null, $max = null){
        if(null === $min){
            $min = 0;
        }
        if(null === $max){
            $max = mt_getrandmax();
        }
        return mt_rand($min, $max);
    }
    
    /**
     * returns random values from an array
     * 
     * if $numReq = 1 it returns one value from array
     * if $numReq > 1 it returns an array with $numReq values               
     *
     * @param array $values
     * @param int $numReq
     * @return mixed|array
     */
    public static function value(array $values, $numReq = 1){
        $numReq = min(max($numReq, 1), count($values));
        if($numReq === 1){
            return $values[array_rand($values, $numReq)];
        }
        $out    = array();
        $keys   = array_rand($values, $numReq);
        foreach($keys as $key){
            $out[] = $values[$key];
        }
        return $out;
    }
    
    /**
     * returns 32 signs long hash
     */
    public static function unique(){
        return md5(uniqid(rand(), true));
    }

}